import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

class FBaseBtn extends StatefulWidget {
  const FBaseBtn({
    super.key,
    this.height,
    this.width,
    this.padding,
    this.child,
    this.decoration,
    this.alignment = Alignment.center,
    required this.onPressed,
  });

  final double? height;
  final double? width;
  final EdgeInsetsGeometry? padding;
  final BoxDecoration? decoration;

  final Widget? child;
  final VoidCallback? onPressed;
  final double? pressedOpacity = 0.7;
  final AlignmentGeometry alignment;

  bool get enabled => onPressed != null;

  static Widget iconText(Widget icon, String text, TextStyle style,
      double space, TextDirection textDirection) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      textDirection: textDirection,
      children: [icon, SizedBox(width: space), Text(text, style: style)],
    );
  }

  @override
  State<FBaseBtn> createState() => _FBaseBtnState();
}

class _FBaseBtnState extends State<FBaseBtn>
    with SingleTickerProviderStateMixin {
  static const Duration kFadeOutDuration = Duration(milliseconds: 120);
  static const Duration kFadeInDuration = Duration(milliseconds: 180);
  final Tween<double> _opacityTween = Tween<double>(begin: 1.0);

  late AnimationController _animationController;
  late Animation<double> _opacityAnimation;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
        duration: const Duration(milliseconds: 200), value: 0.0, vsync: this);
    _opacityAnimation = _animationController
        .drive(CurveTween(curve: Curves.decelerate))
        .drive(_opacityTween);
    _setTween();
  }

  @override
  void didUpdateWidget(FBaseBtn old) {
    super.didUpdateWidget(old);
    _setTween();
  }

  void _setTween() {
    _opacityTween.end = widget.pressedOpacity ?? 1.0;
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  bool _buttonHeldDown = false;

  void _handleTapDown(TapDownDetails event) {
    if (!_buttonHeldDown) {
      _buttonHeldDown = true;
      _animate();
    }
  }

  void _handleTapUp(TapUpDetails event) {
    if (_buttonHeldDown) {
      _buttonHeldDown = false;
      _animate();
    }
  }

  void _handleTapCancel() {
    if (_buttonHeldDown) {
      _buttonHeldDown = false;
      _animate();
    }
  }

  void _animate() {
    if (_animationController.isAnimating) {
      return;
    }
    final bool wasHeldDown = _buttonHeldDown;
    final TickerFuture ticker = _buttonHeldDown
        ? _animationController.animateTo(1.0,
            duration: kFadeOutDuration, curve: Curves.easeInOutCubicEmphasized)
        : _animationController.animateTo(0.0,
            duration: kFadeInDuration, curve: Curves.easeOutCubic);
    ticker.then<void>((void value) {
      if (mounted && wasHeldDown != _buttonHeldDown) {
        _animate();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    final bool enabled = widget.enabled;
    BoxDecoration? decoration = widget.decoration;
    if (widget.height != null && decoration?.borderRadius == null) {
      decoration = decoration?.copyWith(
          borderRadius: BorderRadius.circular(widget.height! / 2));
    }
    return MouseRegion(
      cursor: enabled && kIsWeb ? SystemMouseCursors.click : MouseCursor.defer,
      child: GestureDetector(
          behavior: HitTestBehavior.opaque,
          onTapDown: enabled ? _handleTapDown : null,
          onTapUp: enabled ? _handleTapUp : null,
          onTapCancel: enabled ? _handleTapCancel : null,
          onTap: widget.onPressed,
          child: Semantics(
              button: true,
              child: FadeTransition(
                opacity: _opacityAnimation,
                child: Container(
                  padding: widget.padding,
                  width: widget.width,
                  height: widget.height,
                  decoration: decoration,
                  //alignment: widget.alignment,
                  child: Align(
                      alignment: widget.alignment,
                      widthFactor: 1.0,
                      heightFactor: 1.0,
                      child: widget.child),
                ),
              ))),
    );
  }
}
